home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include "../misc/misc.h"
- #include "dnsconf.h"
- #include "internal.h"
- #include "../paths.h"
-
- extern DNSCONF_HELP_FILE help_dnsconf;
-
- CONFIG_FILE f_boot (ETC_NAMED_BOOT,help_dnsconf
- ,CONFIGF_MANAGED|CONFIGF_OPTIONNAL|CONFIGF_PROBED);
-
- static int dns_is_reverse(const char *str)
- {
- int ret = 0;
- char buf[200];
- strcpy (buf,str);
- strupr (buf);
- char *pt = strstr(buf,".IN-ADDR.ARPA");
- if (pt != NULL){
- if (pt[13] == '\0'){
- ret = 1;
- }
- }
- return ret;
- }
-
-
- PRIVATE void DNS::parse(const char *buf, const char *fpath, int noline)
- {
- char words[10][500];
- for (int i=0; i<10; i++) words[i][0] = '\0';
- int nb = sscanf (buf,"%s %s %s %s %s %s %s %s %s %s"
- ,words[0],words[1],words[2],words[3]
- ,words[4],words[5],words[6],words[7]
- ,words[8],words[9]);
- if (strcmp(words[0],"directory")==0){
- pathcfg.setfrom (words[1]);
- }else if (strcmp(words[0],"cache")==0){
- cachefiles.add (new CACHEFILE (words[1],words[2]));
- }else if (strcmp(words[0],"primary")==0){
- if (dns_is_reverse(words[1])){
- primarys_rev.add (new PRIMARY_REV(words[1]
- ,words[2],pathcfg.get()));
- }else{
- primarys.add (new PRIMARY(words[1],words[2]
- ,pathcfg.get()));
- }
- }else if (strcmp(words[0],"secondary")==0){
- const char *tbip[8];
- for (int i=0; i<8; i++) tbip[i] = words[i+2];
- secondarys.add (new SECONDARY (words[1],words[nb-1]
- ,tbip,nb-3));
- }else if (strcmp(words[0],"forwarders")==0){
- nbforward = nb - 1;
- for (int f=1; f<nb; f++) forwarders[f-1].setfrom(words[f]);
- }else if (strcmp(words[0],"slave")==0){
- slave = 1;
- }else{
- xconf_error ("Invalid keyword %s, file %s line %d\n"
- ,words[0],fpath,noline);
- }
- }
-
-
- /*
- Add the reverse mapping for the loopback network
- */
- PUBLIC void DNS::setlocalhost()
- {
- PRIMARY_REV *pri = new PRIMARY_REV;
- pri->domainv.setfrom ("127.0.0");
- pri->setfromv();
- pri->file.setfrom ("127.0.0");
- pri->addrec (new RECORD_IN_SOA);
- pri->addrec (new RECORD_IN_NS);
- pri->addrec (new RECORD_IN_PTR ("1","localhost."));
- primarys_rev.add (pri);
- }
-
- PUBLIC DNS::DNS()
- {
- slave = 0;
- pathcfg.setfrom ("/var/named");
- nbforward = 0;
- FILE *fin = f_boot.fopen ("r");
- if (fin != NULL){
- char buf[500];
- int noline = 0;
- while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
- noline++;
- strip_end (buf);
- char *pt = str_skip(buf);
- /* #Specification: dnsconf / /etc/named.boot / comments
- Comments in /etc/named.boot are not preserve
- by dnsconf
- */
- if (*pt != '\0' && *pt != ';'){
- parse (buf,f_boot.getpath(),noline);
- }
- }
- }
- }
-
- /*
- Return != 0 if the DNS is not configured at all
- */
- PUBLIC int DNS::empty()
- {
- return primarys.getnb()==0 && primarys_rev.getnb()==0;
- }
-
- PUBLIC void DNS::basiccheck()
- {
- if (cachefiles.getnb()==0){
- cachefiles.add (new CACHEFILE(".","root.cache"));
- }
- FQHOST rfq ("1.0.0.127.in-addr.arpa");
- PRIMARY *rev = primarys_rev.getitem(rfq,NULL);
- if (rev == NULL){
- /* #Specification; dnsconf / check / local domain
- Dnsconf make sure the domain
- 0.0.127.in-addr.arpa is defined. If not it is
- added with a single PTR entry.
- #
- 1 IN PTR localhost.
- #
- */
- setlocalhost();
- }
- }
-
- /*
- Write all configuration files of the DNS.
- Return -1 if any error.
- */
- PUBLIC int DNS::write ()
- {
- int ret = -1;
- /* #Specification: dnsconf / writing /etc/named.boot
- The file /etc/named.boot is rewritten everytime any
- of the DNS files are rewritten. This give a hint
- to netconf to instruct named to restart(reload) just
- by looking at the revision date of /etc/named.boot.
- */
- FILE *fout = f_boot.fopen ("w");
- if (fout != NULL){
- const char *cfg = pathcfg.get();
- struct stat st;
- if (stat(cfg,&st)==-1) mkdir (cfg,0755);
- fprintf (fout,"directory\t%s\n",cfg);
- for (int i=0; i<cachefiles.getnb(); i++){
- CACHEFILE *c = cachefiles.getitem(i);
- fprintf (fout,"cache\t%s\t%s\n",c->domain.get()
- ,c->path.get());
- }
- const char *named_dir = pathcfg.get();
- ret = primarys.write(fout,named_dir);
- ret = primarys_rev.write(fout,named_dir);
- secondarys.write(fout,named_dir);
- if (nbforward > 0){
- fputs ("forwarders",fout);
- for (int f=0; f<MAX_FORWARDERS; f++){
- fputc (' ',fout);
- fputs (forwarders[f].get(),fout);
- }
- fputc ('\n',fout);
- }
- if (slave) fprintf (fout,"slave\n");
- fclose (fout);
- }
- return ret;
- }
- #if 0
- static void qualify(
- const char *fqhost,
- char *host,
- char *domain)
- {
- char *pt = strchr(fqhost,'.');
- if (pt != NULL){
- strcpy (domain,pt+1);
- int len = (int)(pt-fqhost);
- memcpy (host,fqhost,len);
- host[len] = '\0';
- }else{
- strcpy (host,fqhost);
- RESOLV res;
- strcpy (domain,res.domain.get());
- }
- }
- #endif
-
- /*
- Add or replace record (A and PTRs) for a host
- */
- PUBLIC int DNS::set (
- const char *fqhost, // Fully qualified name, or name
- // relative to our own domain
- const char *tbip[], // May set several IP number for
- int nbip) // one host at once
- {
- /* #Specification: dnsconf / set a host / multiple IP
- A host may have several IP number in the DNS. The
- first one is known as the official one. So a
- host may have several A record and several
- corresponding PTR records.
- */
- FQHOST fq (fqhost);
- /* #Specification: dnsconf / setting new spec for a host
- dnsconf use a fairly simple way to update a host
- definition. It simply delete everything relate
- to that host (A record and PTR record) and add
- records in the proper primarys.
-
- There is no chance, using this strategy, to keep the
- original ordering of the record files. This is
- why dnsconf always sort those before writing.
- */
- unset (fqhost);
- // Checking if this DNS is the primary for the domain
- PRIMARY *pri = primarys.getitem(fq,NULL);
- if (pri != NULL){
- for (int i=0; i<nbip; i++){
- pri->set (fq
- ,new RECORD_IN_A("dummy",tbip[i]));
- }
- }
- PRIMARY *onerev = NULL;
- for (int noip=0; noip < nbip; noip++){
- const char *ip = tbip[noip];
- IP_ADDR ipa;
- ipa.setfrom(ip);
- char revdom[40];
- ipa.setrev(revdom);
- FQHOST rfq (revdom);
- PRIMARY *rev = primarys_rev.getitem(rfq,NULL);
- if (rev != NULL){
- char fqdn[PATH_MAX];
- fq.formatfull (fqdn);
- rev->set (rfq
- ,new RECORD_IN_PTR("dummy",fqdn));
- onerev = rev;
- }
- }
- int ret = -1;
- if (pri != NULL || onerev != NULL) ret = 0;
- return ret;
- }
- /*
- Add or replace NS record for a host
- Return -1 if the information could not be added to any domain.
- */
- PUBLIC int DNS::setns (
- const SSTRING &fqhost, // Fully qualified name, or name
- // relative to our own domain
- const SSTRINGS &tbns) // May set several NS for
- // one host at once
- {
- /* #Specification: dnsconf / set a domain / multiple NS
- A domain may have several NS record in the DNS. The
- first one is known as the official one. The others
- are secondaries.
- */
- FQHOST fq (fqhost);
- unsetns (fqhost);
- int ret = -1;
- for (int i=0; i<2; i++){
- /* #Specification: dnsconf / domain and sub-domain
- A DNS may hold information for a domain and
- for sub-domain. When updating the NS records
- of a sub-domain, we also update NS records
- in the parent domain automaticly.
- */
- PRIMARY *pri = primarys.getitem(fq,NULL,i);
- if (pri != NULL){
- int nbns = tbns.getnb();
- for (int i=0; i<nbns; i++){
- SSTRING *ns = tbns.getitem(i);
- if (!ns->is_empty()){
- pri->set (fq
- ,new RECORD_IN_NS("dummy"
- ,ns->get()));
- }
- }
- ret = 0;
- }
- }
- return ret;
- }
- /*
- Add or replace MX record for a host
- */
- PUBLIC int DNS::setmx (
- const SSTRING &fqhost, // Fully qualified name, or name
- // relative to our own domain
- const SSTRINGS &tbmx) // May set several MX for
- // one host at once
- {
- /* #Specification: dnsconf / set a host / multiple MX
- A host may have several MX record in the DNS. dnsconf
- automaticly assign a priority number based on the
- order the different MXs are given.
- */
- FQHOST fq (fqhost);
- unsetmx (fqhost);
- PRIMARY *pri = primarys.getitem(fq,NULL);
- if (pri != NULL){
- int nbmx = tbmx.getnb();
- for (int i=0; i<nbmx; i++){
- SSTRING *mx = tbmx.getitem(i);
- if (!mx->is_empty()){
- pri->set (fq
- ,new RECORD_IN_MX("dummy"
- ,i*5+5,mx->get()));
- }
- }
- }
- return (pri != NULL) ? 0 : -1;
- }
-
- /*
- Remove all reference to a host in the DNS
- */
- PUBLIC void DNS::unset (const char *fqhost)
- {
- FQHOST fq (fqhost);
- char hostpart[200];
- PRIMARY *pri = primarys.getitem(fq,hostpart);
- if (pri != NULL){
- pri->unset (new RECORD_IN_A(hostpart,"1.1.1.1"));
- }
- char full[200];
- fq.formatfull (full);
- for (int i=0; i<primarys_rev.getnb(); i++){
- PRIMARY *pri = primarys_rev.getitem(i);
- pri->unset (new RECORD_IN_PTR("1",full));
- }
- }
-
-
- /*
- Remove all reference to a host in the DNS
- */
- PUBLIC void DNS::unsetns (const SSTRING &fqhost)
- {
- FQHOST fq (fqhost);
- char hostpart[200];
- for (int i=0; i<2; i++){
- PRIMARY *pri = primarys.getitem(fq,hostpart,i);
- if (pri != NULL){
- pri->unset (new RECORD_IN_NS(hostpart,"dummy"));
- }
- }
- }
- /*
- Remove all reference to a host in the DNS
- */
- PUBLIC void DNS::unsetmx (const SSTRING &fqhost)
- {
- FQHOST fq (fqhost);
- char hostpart[200];
- PRIMARY *pri = primarys.getitem(fq,hostpart);
- if (pri != NULL){
- pri->unset (new RECORD_IN_MX(hostpart,0,"dummy"));
- }
- }
-
- /*
- Set a cname record (replace/add/remove)
- */
- PUBLIC void DNS::setcname (const SSTRING &fqhost, const SSTRING &cname)
- {
- FQHOST fq (fqhost);
- char hostpart[200];
- PRIMARY *pri = primarys.getitem(fq,hostpart);
- if (pri != NULL){
- pri->unset (new RECORD_IN_CNAME(hostpart,"dummy"));
- if (!cname.is_empty()){
- pri->set (fq,new RECORD_IN_CNAME(hostpart
- ,cname.get()));
- }
- }
- }
-
-
-